package org.anderground.editor.edits;

import static org.anderground.editor.edits.Editor.edit;

import javax.swing.undo.AbstractUndoableEdit;
import javax.swing.undo.CannotRedoException;
import javax.swing.undo.CannotUndoException;
import javax.swing.undo.UndoableEdit;

import org.anderground.core.graphics.PointF;
import org.anderground.core.model.Station;
import org.anderground.core.util.Point;

/**
 * @author Eldar Abusalimov
 */
public class MoveStationLabelAction extends Action {

	private Station.Label label;
	private float dx, dy;

	public MoveStationLabelAction(float dx, float dy, Station.Label label) {
		this.label = label;
		this.dx = dx;
		this.dy = dy;
	}

	@Override
	UndoableEdit perform() throws ActionException {
		return new PointEdit(dx, dy, label);
	}

	/**
	 * @author Eldar Abusalimov
	 */
	@SuppressWarnings("serial")
	private static class PointEdit extends AbstractUndoableEdit {

		private Station.Label label;
		private PointF pointF;
		private PointF delta;

		/**
		 * 
		 * @param dx
		 * @param dy
		 * @param coords
		 */
		public PointEdit(float dx, float dy, Station.Label label) {
			this.label = label;
			pointF = new PointF(label.getOffset().getX(), label.getOffset()
					.getY());
			delta = new PointF(dx, dy);
			shift(delta);
		}

		@Override
		public void undo() throws CannotUndoException {
			PointF minusDelta = new PointF();
			minusDelta.subtract(delta);
			shift(minusDelta);
		}

		@Override
		public void redo() throws CannotRedoException {
			shift(delta);
		}

		@Override
		public boolean addEdit(UndoableEdit anEdit) {
			if (anEdit instanceof PointEdit) {
				PointEdit pointEdit = (PointEdit) anEdit;
				if (label == pointEdit.label) {
					delta.add(pointEdit.delta);
					shift(pointEdit.delta);
					return true;
				}
			}
			return false;
		}

		private void shift(PointF delta) {
			shift(delta.x, delta.y);
		}

		private void shift(float dx, float dy) {
			pointF.x += dx;
			pointF.y += dy;
			edit(label).setOffset(new Point((int) pointF.x, (int) pointF.y));
		}

	}

}
